/**
 * Copyright 2009 Adam Ruggles.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.code.sapien.model;

import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Version;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

/**
 * User entity data model.
 * @author Adam
 * @version $Id: User.java 24 2009-05-15 04:38:19Z a.ruggles $
 * 
 * Created on Feb 7, 2009 at 4:25:16 PM 
 */
@javax.persistence.Entity @Table(name = "sapien_users")
@NamedQueries({
	@NamedQuery(name = "user.getByEmail",
			query = "SELECT u FROM com.google.code.sapien.model.User u WHERE u.email = :email"),
	@NamedQuery(name = "user.getByUsername",
			query = "SELECT u FROM com.google.code.sapien.model.User u WHERE u.username = :username")
})
public class User implements Serializable, Comparable<User> {
	/**
	 * Serial Version UID.
	 */
	private static final long serialVersionUID = -3311984760863927440L;

	/**
     * Active flag for the user account.
     */
    private Boolean active;

    /**
     * The date and time the user was created.
     */
    private Date created;

    /**
     * The email address.
     */
    private String email;

    /**
     * Unique identifier.
     */
    private Long id;

    /**
     * The date and time the post was last updated.
     */
    private Date modified;

    /**
     * The password.
     */
    private String password;

    /**
     * A Set of roles the user belongs to.
     */
    private Set<Role> roles = new HashSet<Role>();

    /**
     * The unique username.
     */
    private String username;

    /**
     * The version for optimistic concurrency control.
     */
    private Integer version;

    /**
     * {@inheritDoc}
     * @see java.lang.Comparable#compareTo(java.lang.Object)
     */
	public int compareTo(final User user) {
		int value = -1;
		if (this.username != null && user != null && user.getUsername() != null) {
			value = this.username.compareTo(user.getUsername());
		}
		return value;
	}

	/**
     * {@inheritDoc}
     * @see java.lang.Object#equals(java.lang.Object)
     */
	@Override
	public boolean equals(final Object obj) {
		if (this == obj) {
			return true;
		}
		if (!(obj instanceof User)) {
			return false;
		}
		final User rhs = (User) obj;
		return new EqualsBuilder()
			.append(username, rhs.getUsername())
			.isEquals();
	}

    /**
	 * Returns active.
	 * @return the active.
	 */
	@Basic(optional = false)
	public Boolean getActive() {
		return active;
	}

	/**
	 * Returns created.
	 * @return the created.
	 */
	@Basic(optional = false) @Temporal(TemporalType.TIMESTAMP)
	public Date getCreated() {
		return created;
	}

	/**
	 * Returns email.
	 * @return the email.
	 */
	@Column(nullable = false, unique = true)
	public String getEmail() {
		return email;
	}

	/**
	 * Returns id.
	 * @return the id.
	 */
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
	public Long getId() {
		return id;
	}

	/**
	 * Returns modified.
	 * @return the modified.
	 */
    @Basic(optional = false) @Temporal(TemporalType.TIMESTAMP)
	public Date getModified() {
		return modified;
	}

	/**
	 * Returns password.
	 * @return the password.
	 */
    @Column(length = 60, nullable = false)
	public String getPassword() {
		return password;
	}

	/**
	 * Returns roles.
	 * @return the roles.
	 */
	@ManyToMany(fetch = FetchType.LAZY)
	@JoinTable(name = "sapien_users_roles",
			joinColumns = @JoinColumn(name = "user_id"),
			inverseJoinColumns = @JoinColumn(name = "role_id"))
	public Set<Role> getRoles() {
		return roles;
	}

	/**
	 * Returns username.
	 * @return the username.
	 */
    @Column(length = 50, nullable = false, unique = true)
	public String getUsername() {
		return username;
	}

	/**
	 * Returns version.
	 * @return the version.
	 */
    @Version
	public Integer getVersion() {
		return version;
	}

	/**
	 * {@inheritDoc}
	 * @see java.lang.Object#hashCode()
	 */
	public int hashCode() {
		return new HashCodeBuilder(37, 11)
			.append(username)
			.toHashCode();
	}

	/**
	 * Sets active.
	 * @param active the active to set.
	 */
	public void setActive(final Boolean active) {
		this.active = active;
	}

	/**
	 * Sets created.
	 * @param created the created to set.
	 */
	public void setCreated(final Date created) {
		this.created = created;
	}

	/**
	 * Sets email.
	 * @param email the email to set.
	 */
	public void setEmail(final String email) {
		this.email = email;
	}

	/**
	 * Sets id.
	 * @param id the id to set.
	 */
	public void setId(final Long id) {
		this.id = id;
	}

	/**
	 * Sets modified.
	 * @param modified the modified to set.
	 */
	public void setModified(final Date modified) {
		this.modified = modified;
	}

	/**
	 * Sets password.
	 * @param password the password to set.
	 */
	public void setPassword(final String password) {
		this.password = password;
	}

	/**
	 * Sets roles.
	 * @param roles the roles to set.
	 */
	public void setRoles(final Set<Role> roles) {
		this.roles = roles;
	}

	/**
	 * Sets username.
	 * @param username the username to set.
	 */
	public void setUsername(final String username) {
		this.username = username;
	}

	/**
	 * Sets version.
	 * @param version the version to set.
	 */
	public void setVersion(final Integer version) {
		this.version = version;
	}

	/**
	 * {@inheritDoc}
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		return new ToStringBuilder(this)
			.append("id", id)
			.append("username", username)
			.append("email", email)
			.append("created", created)
			.append("modified", modified)
			.append("active", active)
			.toString();
	}
}
